#pragma once

#include <iostream>
#include <functional>
#include <string>
#include <cassert>
#include <cstdio>
#include <pthread.h>

#define NAME_NUM 1024

class Thread;//先声明这个类

template <class T>
class Context/*用于包装线程的信息*/
{
public:
    Context():this_(nullptr), args_(nullptr){ }
    Context(T* _this, void* args = nullptr):this_(_this), args_(args){ }
public:
    T* this_;
    void* args_;//参数
};

class Thread/*封装一个自己的线程库*/
{
public:
    using func_t = std::function<void*(void*)>;//重命名函数类型

public:
    Thread()
    {
        char namebuffer[NAME_NUM];
        snprintf(namebuffer, sizeof namebuffer, "thread-> %d", num_++);
        name_ = namebuffer;
    }

    void start(func_t func, void* args = nullptr)
    {
        func_ = func;
        args_ = args;
        Context<Thread>* ctx = new Context<Thread>();
        ctx->this_ = this;
        ctx->args_ = args_;
        int n = pthread_create(&tid_, nullptr, start_routine, ctx);
        assert(n == 0);
        (void)n;
    }
 private:

    static void* start_routine(void* args)//默认自带了一个this指针，所以该函数的类型为 void*(*)(void*,this):不是void*(*)(void*),不符合要求
    {
        Context<Thread>* ctx = static_cast<Context<Thread>*>(args);
        void * ret = ctx->this_->run(ctx->args_);
        delete ctx;
        return ret;
        //return func();//err：静态方法只能调用静态成员
    }

    void* run(void* args)//运行函数，用于包装func_
    {
        return func_(args);
    }

public:   
    int join()//线程等待
    {
        int n = pthread_join(tid_, nullptr);
        assert(n == 0);
        return n;
    }
    
    pthread_t gettid()
    {
        return tid_;
    }

    std::string getname()
    {
        return name_;
    }

    ~Thread()
    {
        //do nothing
    }

private:
    pthread_t tid_;//线程id
    std::string name_;//线程名字
    static int num_;//线程编号
    void* args_;//参数
    func_t func_;//子线程进行的操作
};

int Thread::num_ = 1;